const {
	result_success,
	result_error
} = require('http-result-modle')
const {
	wmz_provider_info
} = require('config-wmz-provider')
const {
	get_qid_no,
	getUuid
} = require('common-uuid');
const db = uniCloud.database({
	provider: 'tencent',
	spaceId: 'tcb-fy6f7f4nm7mhifi-6c366c810511'
});
const FormData = require('form-data');
async function test() {
	 console.log(123)
	return result_error("错误")
}
async function wechatRequestCommon(params) {
	let url = params.url
	let data = params.data || {}
	let method = params.method || 'POST'
	let headers = params.headers || {}
	let res = await uniCloud.httpclient.request(url, {
		method: method,
		headers: headers,
		data: data,
		contentType: 'json', // 指定以application/json发送data内的数据
		dataType: 'json' // 指定返回值为json格式，自动进行parse
	})
	/* try {
		await db.collection('logs-wmz-wechat-sdk').add({
			method: method,
			data: data,
			res: res,
			create_time: new Date().getTime()
		})
	} catch (e) {
		console.log('报错日志失败')
		console.log(e)
	} */
	if (res.status === 200 && !res.data.errcode) {
		return result_success(res.data)
	}
	return result_error(res.data)
}
async function getComponentToken(component_appid, tokenTimeOut) {
	let db_commentAccount = await db.collection('wmz-wechat-component-account').where({
		component_appid: component_appid
	}).field({
		component_appid: true,
		component_appsecret: true,
		component_verify_ticket: true,
		component_access_token: true,
		access_token_updateTime: true,
		expires_in: true
	}).get()
	if (db_commentAccount && db_commentAccount.data && db_commentAccount.data.length > 0) {
		db_commentAccount = db_commentAccount.data[0]
	} else {
		return result_error("没有获取到平台commentAccount信息！")
	}
	if (!tokenTimeOut) {
		let nowTimestamp = new Date().getTime()
		if (db_commentAccount.component_access_token && ((nowTimestamp - db_commentAccount
				.access_token_updateTime) < (db_commentAccount.expires_in - 10) * 1000)) {
			return result_success(db_commentAccount.component_access_token)
		}
	}
	if (!db_commentAccount.component_verify_ticket) {
		return result_error("没有获取到平台verify_ticket信息！")
	}
	const url = "https://api.weixin.qq.com/cgi-bin/component/api_component_token"
	let res = await wechatRequestCommon({
		url: url,
		data: {
			component_appid: db_commentAccount.component_appid,
			component_appsecret: db_commentAccount.component_appsecret,
			component_verify_ticket: db_commentAccount.component_verify_ticket
		}
	})
	if (res.data.component_access_token) {
		await db.collection('wmz-wechat-component-account').doc(db_commentAccount._id).update({
			component_access_token: res.data.component_access_token,
			access_token_updateTime: new Date().getTime(),
			expires_in: res.data.expires_in
		})
		return result_success(res.data.component_access_token)
	} else {
		return result_error(res.data.errmsg, res.data.errcode)
	}
}
async function getAuthorizerToken(_id, tokenTimeOut) {
	let appletInfo = await db.collection('wmz-applet-info').doc(_id).field({
		'wechat.app_id': true,
		'wechat.authorization_code': true,
		'wechat.access_token': true,
		'wechat.authorizer_refresh_token': true,
		'wechat.access_token_updateTime': true,
		'wechat.expires_in': true,
		'wechat.auth_app_id': true,
		space_id: true
	}).get()

	if (appletInfo && appletInfo.data && appletInfo.data.length > 0) {
		appletInfo = appletInfo.data[0]
	} else {
		return result_error("没有获取到商家微信小程序信息！appId:" + _id)
	}
	if (!appletInfo.wechat.access_token) {
		tokenTimeOut = true
	}
	let auth_app_id = appletInfo.wechat.auth_app_id
	if (!tokenTimeOut) {
		let nowTimestamp = new Date().getTime()
		if (appletInfo.access_token && ((nowTimestamp - appletInfo
				.access_token_updateTime) < (appletInfo.expires_in - 10) * 1000)) {
			return result_success(appletInfo.access_token)
		}
	}
	let componentToken = await getComponentToken(appletInfo.wechat.app_id)
	if (componentToken.code === 200) {
		componentToken = componentToken.data
	} else {
		return result_error("获取componentToken失败" + componentToken.msg)
	}
	if (!appletInfo.wechat.authorizer_refresh_token) {
		let url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=" +
			componentToken
		let res = await wechatRequestCommon({
			url: url,
			data: {
				component_appid: appletInfo.wechat.app_id,
				authorizer_appid: auth_app_id,
				authorization_code: appletInfo.wechat.authorization_code
			}
		})
		if (res.code === 200) {
			await db.collection('wmz-applet-info').doc(appletInfo._id).update({
				wechat: {
					access_token: res.data.authorization_info.authorizer_access_token,
					authorizer_refresh_token: res.data.authorization_info.authorizer_refresh_token,
					access_token_updateTime: new Date().getTime(),
					expires_in: res.data.authorization_info.expires_in
				}
			})
			if (appletInfo.space_id) {
				let tDb = uniCloud.database({
					provider: 'tencent',
					spaceId: appletInfo.space_id
				})
				await tDb.collection('wmz-applet-info').doc(appletInfo._id).update({
					wechat: {
						access_token: res.data.authorization_info.authorizer_access_token,
						authorizer_refresh_token: res.data.authorization_info.authorizer_refresh_token,
						access_token_updateTime: new Date().getTime(),
						expires_in: res.data.authorization_info.expires_in
					}
				})
			}
			return result_success(res.data.authorization_info.authorizer_access_token)
		} else {
			return result_error("获取access_token失败" + msg.msg)
		}
	} else {
		let url = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=" +
			componentToken
		let res = await wechatRequestCommon({
			url: url,
			data: {
				component_appid: appletInfo.wechat.app_id,
				authorizer_appid: auth_app_id,
				authorizer_refresh_token: appletInfo.wechat.authorizer_refresh_token
			}
		})
		if (res.code === 200) {
			await db.collection('wmz-applet-info').doc(appletInfo._id).update({
				wechat: {
					access_token: res.data.authorizer_access_token,
					authorizer_refresh_token: res.data.authorizer_refresh_token,
					access_token_updateTime: new Date().getTime(),
					expires_in: res.data.expires_in
				}
			})
			if (appletInfo.space_id) {
				let tDb = uniCloud.database({
					provider: 'tencent',
					spaceId: appletInfo.space_id
				})
				await tDb.collection('wmz-applet-info').doc(appletInfo._id).update({
					wechat: {
						access_token: res.data.authorizer_access_token,
						authorizer_refresh_token: res.data.authorizer_refresh_token,
						access_token_updateTime: new Date().getTime(),
						expires_in: res.data.expires_in
					}
				})
			}
			return result_success(res.data.authorizer_access_token)
		} else {
			return result_error("获取access_token失败" + res.data.errmsg)
		}
	}
}
async function getSignAuthorV3(mchid, privateKeyInfo, serialNo, requestType, requestUrl, timestamp, nonceStr,
	paramsObj) {
	let signUrl, signStr, metaStr
	if (!mchid) {
		return result_error("商户号mchid不能为空！")
	}
	if (!privateKeyInfo || (!privateKeyInfo.privateKeyFileName && !privateKeyInfo.privateKey)) {
		return result_error("密钥信息不存在！")
	}
	if (!serialNo) {
		return result_error("证书序列号serialNo不能为空！")
	}
	if (!requestType) {
		return result_error("请求类型requestType不能为空！")
	}
	if (!requestUrl) {
		return result_error("请求地址requestUrl不能为空！")
	}
	if (!timestamp) {
		return result_error("请求时间戳timestamp不能为空！")
	}
	if (!nonceStr) {
		return result_error("请求随机串nonceStr不能为空！")
	}

	signUrl = requestUrl.replace("https://api.mch.weixin.qq.com", "")
	requestType = requestType.toUpperCase()
	if (timestamp.toString().length > 10) {
		timestamp = parseInt(timestamp / 1000)
	}

	signStr = '' + requestType + '\n'
	signStr = signStr + signUrl + '\n'
	signStr = signStr + timestamp + '\n'
	signStr = signStr + nonceStr + '\n'
	if (requestType !== "GET" && paramsObj) {
		metaStr = JSON.stringify(paramsObj)
		signStr = signStr + metaStr
	}
	signStr = signStr + '\n'

	let signResult = await uniCloud.callFunction({
		name: "wmz-crypto",
		data: {
			path: "/encryptUtills/sha256WithRsaToBase64",
			data: {
				dataInfo: {
					data: signStr
				},
				privateKeyFileName: privateKeyInfo.privateKeyFileName,
				privateKey: privateKeyInfo.privateKey
			}
		}
	})
	signResult = signResult.result
	if (signResult.code !== 200) {
		return signResult
	}
	let author = 'WECHATPAY2-SHA256-RSA2048 mchid=\"' + mchid + '\"'
	author = author + ',nonce_str=\"' + nonceStr + '\"'
	author = author + ',timestamp=\"' + timestamp + '\"'
	author = author + ',serial_no=\"' + serialNo + '\"'
	author = author + ',signature=\"' + signResult.data + '\"'
	return result_success(author)
}
async function signAuthorV3(mchid, requestType, requestUrl, paramsObj, timestamp,
	nonceStr) {
	let serialNo, privateKeyFileName
	for (var i in wmz_provider_info) {
		if (wmz_provider_info[i].MCH_ID == mchid) {
			serialNo = wmz_provider_info[i].SERIAL_NO
			privateKeyFileName = wmz_provider_info[i].PRIVATE_KEY_FILE
		}
	}
	if (!mchid) {
		return result_error("服务商商户号mchid获取失败")
	}
	if (!serialNo) {
		return result_error("服务商证书序列号serialNo获取失败")
	}
	if (!privateKeyFileName) {
		return result_error("服务商证书文件privateKeyFileName获取失败")
	}
	let privateKeyInfo = {
		privateKeyFileName: privateKeyFileName
	}
	if (!timestamp) {
		timestamp = parseInt(new Date().getTime() / 1000)
	}
	if (!nonceStr) {
		nonceStr = get_qid_no()
	}
	return getSignAuthorV3(mchid, privateKeyInfo, serialNo, requestType, requestUrl, timestamp,
		nonceStr, paramsObj)
}
async function merchantMediaUploadV3(imageUrl, filename, mchid, serialNo, sha256, privateKeyFileName, privateKey) {
	if (!imageUrl) {
		return result_error("图片地址不能为空！")
	}
	if (!filename) {
		return result_error("图片文件名称不能为空！")
	}
	if (!mchid) {
		return result_error("商户号不能为空！")
	}
	if (!serialNo) {
		return result_error("商户API证书序列号不能为空！")
	}
	if (!privateKeyFileName && !privateKey) {
		return result_error("商户API证书名称和商户私钥不能同时为空！")
	}
	const res = await uniCloud.httpclient.request(imageUrl, {
		method: 'GET',
		contentType: 'json', // 指定以application/json发送data内的数据
	})
	let newBuffer = Buffer.from(res.data, "latin1")

	const form = new FormData()
	let metaStr = JSON.stringify({
		"filename": filename,
		"sha256": sha256
	})
	form.append('meta', metaStr);
	form.append('file', res.data, {
		filename: filename,
		contentType: 'image/jpeg'
	});
	let nonce_str = getUuid()
	let timestamp = parseInt(new Date().getTime() / 1000)
	let signStr = 'POST\n'
	signStr = signStr + '/v3/merchant/media/upload\n'
	signStr = signStr + timestamp + '\n'
	signStr = signStr + nonce_str + '\n'
	signStr = signStr + metaStr + '\n'
	let signResult = await uniCloud.callFunction({
		name: "wmz-crypto",
		data: {
			path: "/encryptUtills/sha256WithRsaToBase64",
			data: {
				dataInfo: {
					data: signStr
				},
				privateKeyFileName: privateKeyFileName,
				privateKey: privateKey
			}
		}
	})
	let author = 'WECHATPAY2-SHA256-RSA2048 mchid=\"' + mchid + '\"'
	author = author + ',nonce_str=\"' + nonce_str + '\"'
	author = author + ',timestamp=\"' + timestamp + '\"'
	author = author + ',serial_no=\"' + serialNo + '\"'
	author = author + ',signature=\"' + signResult.result.data + '\"'
	let resUp = await uniCloud.httpclient.request(
		'https://api.mch.weixin.qq.com/v3/merchant/media/upload', {
			method: 'POST',
			content: form.getBuffer(), // 请求内容
			headers: {
				"Content-Type": "multipart/form-data",
				"authorization": author
			}, // 请求头
			dataType: 'json' // 此处指定为json表示将此请求的返回值解析为json
		})
	if (resUp.status === 200) {
		return result_success(resUp.data)
	}
	return result_error(resUp.data)
}
module.exports = {
	_before: function() { // 通用预处理器

	},
	test,
	wechatRequestCommon,
	getComponentToken,
	getAuthorizerToken,
	async v3Certificates(mchid) {
		console.log(mchid)
		const Url = "https://api.mch.weixin.qq.com/v3/certificates"
		let author = await signAuthorV3(mchid, "GET", Url)
		console.log(author)
		if (author.code === 200) {
			author = author.data
		} else {
			return result_error("author签名异常！")
		}
		let resUp = await uniCloud.httpclient.request(Url, {
			method: 'GET',
			headers: {
				"Accept": "	application/json",
				"authorization": author
			},
			data: {},
			contentType: 'application/json', // 指定以application/json发送data内的数据
			dataType: 'json' // 指定返回值为json格式，自动进行parse
		})
		if (resUp.status === 200) {
			let data = resUp.data.data[0]
			let ciphertext = data.encrypt_certificate.ciphertext
			let nonce = data.encrypt_certificate.nonce
			let associated_data = data.encrypt_certificate.associated_data
			let API_V3_KEY
			for (var i in wmz_provider_info) {
				if (wmz_provider_info[i].MCH_ID == mchid) {
					API_V3_KEY = wmz_provider_info[i].API_V3_KEY
				}
			}
			let certificate = await uniCloud.callFunction({
				name: "wmz-crypto",
				data: {
					path: "/encryptUtills/decodeV3CertificatesWx",
					data: {
						ciphertext: ciphertext,
						nonce: nonce,
						apiV3Key: API_V3_KEY,
						associated_data: associated_data
					}
				}
			})
			certificate = certificate.result
			if (certificate.code === 200) {
				return result_success({
					certificate: certificate.data,
					serial_no: data.serial_no
				})
			} else {
				return certificate
			}
		}
		return result_error(resUp)
	},
	getSignAuthorV3,
	signAuthorV3,
	async fileUploadV3(mchid, imageUrl, sha256, filename) {
		let serialNo, privateKeyFileName
		if (!imageUrl) {
			return result_error("图片地址imageUrl不能为空！")
		}
		if (!filename) {
			let imageInfo = imageUrl.split("/")
			filename = imageInfo[imageInfo.length - 1]
		}
		for (var i in wmz_provider_info) {
			if (wmz_provider_info[i].MCH_ID == mchid) {
				serialNo = wmz_provider_info[i].SERIAL_NO
				privateKeyFileName = wmz_provider_info[i].PRIVATE_KEY_FILE
			}
		}
		if (!mchid) {
			return result_error("服务商商户号mchid获取失败")
		}
		if (!serialNo) {
			return result_error("服务商证书序列号serialNo获取失败")
		}
		if (!privateKeyFileName) {
			return result_error("服务商证书文件privateKeyFileName获取失败")
		}

		return merchantMediaUploadV3(imageUrl, filename, mchid, serialNo, sha256,
			privateKeyFileName)
	},
	async cgiBinMediaUpload(access_token, type, fileUrl, filename) {
		let url = "https://api.weixin.qq.com/cgi-bin/media/upload"
		url = url + "?access_token=" + access_token + "&type=" + type
		const resFile = await uniCloud.httpclient.request(fileUrl, {
			method: 'GET',
			contentType: 'json', // 指定以application/json发送data内的数据
		})
		const form = new FormData()
		form.append('media', resFile.data, {
			filename: filename,
			contentType: 'image/jpeg'
		});
		let res = await uniCloud.httpclient.request(url, {
			method: 'POST',
			content: form.getBuffer(), // 请求内容
			headers: {
				"Content-Type": "multipart/form-data"
			}, // 请求头
			dataType: 'json' // 此处指定为json表示将此请求的返回值解析为json
		})
		if (res.status === 200) {
			return result_success(res.data)
		} else {
			return result_error(res.data)
		}
	}

}